#include "model3d.hpp"

static float maxSize = 2.f;

Model3D::Model3D(){ }

void Model3D::draw()
{
    bindVBOs();
    glColor3f(0.f, 0.f, 1.f);
    glDrawElements(GL_TRIANGLES, _indiceArray.size(), GL_UNSIGNED_INT, 0);
}

void Model3D::drawSample()
{
    bindVBOsSample();
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
    glDrawElements(GL_POINTS, _indicesSampleArray.size(), GL_UNSIGNED_INT, 0);
}

void Model3D::init()
{
    initModelView();

    PolyList p(_vertexArray, _indiceArray);

    std::vector<QVector3D> samplesList = PolyList::sceneSampling(p, 50000);

	for(size_t i = 0; i < samplesList.size(); i++)
    {
        _verticesSampleArray.push_back(samplesList.at(i).x());
        _verticesSampleArray.push_back(samplesList.at(i).y());
        _verticesSampleArray.push_back(samplesList.at(i).z());

        _indicesSampleArray.push_back(i);
    }

    _vboVertices = createVBO(QGLBuffer::VertexBuffer, QGLBuffer::StaticDraw, _vertexArray);
    _vboIndices = createVBO(QGLBuffer::IndexBuffer, QGLBuffer::StaticDraw, _indiceArray);

    _vboVerticesSample = createVBO(QGLBuffer::VertexBuffer, QGLBuffer::StaticDraw, _verticesSampleArray);
    _vboIndicesSample = createVBO(QGLBuffer::IndexBuffer, QGLBuffer::StaticDraw, _indicesSampleArray);
}

const std::string & Model3D::getName() const
{
    return _name;
}

void Model3D::setName(std::string name)
{
    _name = name;
}

const boundingBox & Model3D::getBoundingBox() const
{
      return _box;
}

void Model3D::setBoundingBox(float min[3], float max[3])
{
    _box.min = QVector3D(min[0], min[1], min[2]);
    _box.max = QVector3D(max[0], max[1], max[2]);
}

QMatrix4x4 Model3D::getModelView()
{
    return _modelView;
}

void Model3D::setModelView(QMatrix4x4 modelView)
{
    _modelView = modelView;
}

void Model3D::addColor(){ }

void Model3D::addVertex(float vertexCoord)
{
    _vertexArray.push_back(vertexCoord);
}

void Model3D::addFace(unsigned int faceIndice)
{
    _indiceArray.push_back(faceIndice);
}

void Model3D::initModelView()
{
    float ratio = maxSize / qMax(qMax(_box.max.x() - _box.min.x(), _box.max.y() - _box.min.y()),_box.max.z() - _box.min.z());

    _modelView.scale(ratio, ratio, ratio);
}

void Model3D::bindVBOs()
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_INDEX_ARRAY);

    if(_vboVertices.bind())
    {
        glVertexPointer(3, GL_FLOAT, 0, 0);
        _vboVertices.release();
    }
    else
        qWarning() << "vboVertices.bind() error";

    _vboIndices.bind();
}

void Model3D::bindVBOsSample()
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_INDEX_ARRAY);

    if(_vboVerticesSample.bind())
    {
        glVertexPointer(3, GL_FLOAT, 0, 0);
        _vboVerticesSample.release();
    }
    else
        qWarning() << "vboVerticesSample.bind() error";

    _vboIndicesSample.bind();
}
